using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using DailyReport.Core.Data.Dao;
using DailyReport.Core.Util;
using NHibernate;
using NHibernate.Expression; 
using log4net;
namespace DailyReport.NHibernateDao.Data.Dao
{
    public class NHibernateBaseDao<T, ID> : IGenericDao<T, ID>
    {
        protected ILog log = LogManager.GetLogger("DailyReportManager");
        private Type persitentType = typeof(T);

        protected ISession session;

        public ISession Session
        {
            set { session = value; }
        }



        private static ILog mylog = LogManager.GetLogger("NHibernateDao"); 

        public T GetById(ID id, bool shouldLock)
        {
            T entity;
            if (shouldLock)
            {
                entity = (T)session.Load(persitentType, null, shouldLock? LockMode.Read:LockMode.Read);
            }
            else
            {
                entity = (T)session.Load(persitentType, id);
            }

            return entity;


        }

        public List<T> GetByCriteria(params ICriterion[] criterion)
        {
            ICriteria criteria = session.CreateCriteria(persitentType);
            foreach (ICriterion criterium in criterion)
            {
                
                criteria.Add(criterium);
            }

            return ListUtil.ConvertToGenericList<T>(criteria.List());

        }


        public List<T> GetAll()
        {
            return GetByCriteria();
        }

        public List<T> GetByExample(T exampleInstance, params string[] propertiesToExclude)
        {
            ICriteria criteria = session.CreateCriteria(persitentType);
            Example example = Example.Create(exampleInstance);

            foreach (string propertyToExclude in propertiesToExclude)
            {
                example.ExcludeProperty(propertyToExclude);
            }

            criteria.Add(example);

            return ListUtil.ConvertToGenericList<T>(criteria.List());

        }

        public T GetUniqueByExample(T exampleInstance, params string[] propertiesToExclude)
        {
            List<T> foundList = GetByExample(exampleInstance, propertiesToExclude);

            if (foundList.Count > 1)
            {
                throw new NonUniqueResultException(foundList.Count);
            }

            if (foundList.Count > 0)
            {
                return foundList[0];
            }
            else
            {
                return default(T);
            }
        }

        public ID SaveAndReturn(T entity)
        {
            return (ID)session.Save(entity);
        }

        public void Save(T entity)
        {
            session.Save(entity);
        }

        public void SaveOrUpdate(T entity)
        {
            session.SaveOrUpdate(entity);
        }

        public void Delete(T entity)
        {
            session.Delete(entity);
        }

        public IList getBaseInstancesList(string sortExpression, int maxRows, int startRowIndex)
        {
            ICriteria criteria = session.CreateCriteria(persitentType);

            if (sortExpression != null && sortExpression.Length > 0)
                criteria.AddOrder(Order.Asc(sortExpression));

            criteria.SetFirstResult(startRowIndex)
                     .SetMaxResults(maxRows);
            return criteria.List();
        }
        public int getBaseInstancesCount()
        {
            IQuery query = session.CreateQuery("select count(ID) from " + persitentType);
            return (int) query.UniqueResult();
        }
    }
}
